#include maps\_utility;
#include common_scripts\utility;
#include maps\_anim;
#include maps\camp_assault_code;

/***********************************************************************
Gameplay
***********************************************************************/

introRide()
{
	// Boat 1 Set Up
	guys = [];


	level.redShirt1 gun_remove();

	boat1 = getEnt( "opening_boat", "targetname" );
	assert( isDefined( boat1 ) );

	level.redShirt1 LinkTo( boat1, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );
	level.Roebuck LinkTo( boat1, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );

	guys[ 0 ] = level.redShirt1;
	guys[ 1 ] = level.Roebuck;

	boat1.num = 1;
	boat1.guys = guys;
	boat1 thread anim_loop( guys, "boat_calm", undefined, "exit_boat", boat1 );

	// Player Setup
	playerSpot = getEnt( "opening_player_pov", "targetname" );
	assert( isDefined( playerSpot ) );

	playerSpot LinkTo( boat1 );

	players = get_players();
	for( x = 0 ; x < players.size ; x++ )
	{
		player = players[ x ];
		player SetOrigin( playerSpot.origin );
		player PlayerLinkTo( playerSpot );
		player AllowCrouch( false );
		player AllowProne( false );
	}

	hide_all_player_models();

	// Boat 2 Set Up
	guys = [];

	boat2 = getEnt( "opening_boat2", "targetname" );
	assert( isDefined( boat2 ) );

	level.redShirt2 gun_remove();

	level.redShirt2 LinkTo( boat2, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );
	level.Polonsky LinkTo( boat2, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );
	level.Sullivan LinkTo( boat2, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );

	guys[ 0 ] = level.redShirt2;
	guys[ 1 ] = level.Polonsky;
	guys[ 2 ] = level.Sullivan;

	boat2.num = 2;
	boat2.guys = guys;
	boat2 thread anim_loop( guys, "boat_calm", undefined, "exit_boat", boat2 );

	// Boat Movement

	level waittill ( "finished final intro screen fadein" );

	boat1 thread boatLogic();
	boat2 thread boatLogic();

	wait ( 3 );

	level.Roebuck speak( "orders", playerSpot );

	wait ( 2.7 );

	level.Roebuck thread speak( "check" );

	trigger_wait ( "ridge_crossing", "targetname" );

	// HeadLights
	waittillframeend;
	thread truckHeadLights( "truck1" );
	thread truckHeadLights( "truck2" );

	wait ( 0.9 );

	level.Polonsky speak( "look" );

	wait ( 0.2 );

	//point = getStruct( "lookAtPoint_opening", "targetname" );
	//assert( isDefined( point ) );

	//level.Roebuck setLookAt( point.origin, 1000 );

	boat2.guys[ 0 ] speak( "head_down" );

	// Scripted Truck Scene
	truck = getEnt( "truck2", "targetname" );
	assert( isDefined( truck ) );

	flag_wait ( "bridgeSceneInPlace" );

	driver = truck.riders[ 0 ];
	assert( isDefined( driver ) );
	driver gun_remove();
	driver.animName = "driver";
	driver.ignoreme = true;
	driver.ignoreall = true;
	driver set_run_anim("patrol_walk");

	passenger = truck.riders[ 1 ];
	assert( isDefined( passenger ) );
	passenger gun_remove();
	passenger.animName = "passenger";
	passenger.ignoreme = true;
	passenger.ignoreall = true;
	passenger set_run_anim("patrol_walk");

	talkSpot1 = getNode( "talkingSpot1", "targetname" );
	assert( isDefined( talkSpot1 ) );

	talkSpot2 = getNode( "talkingSpot2", "targetname" );
	assert( isDefined( talkspot2 ) );

	passenger setGoalNode( talkSpot2 );
	driver setGoalNode( talkSpot1 );

	truck.unload_group = "all";
	truck notify ( "unload" );
	truck waittill ( "unloaded" );

	truck playSound( "truck_door_close", "door_close" );
	truck waittill ( "door_close" );

	flag_wait_all( "passenger_ready", "driver_ready" );

	wait ( 0.6 );

	talkSpot1 thread anim_loop_solo( passenger, "talking_loop", undefined, "stop" );
	talkSpot2 thread anim_loop_solo( driver, "talking_loop", undefined, "stop" );

	thread introRideJapChatter( driver, passenger );

	endTrig = getEnt( "bridgeSceneEnd", "targetname" );
	assert( isDefined( endTrig ) );

	endTrig waittill ( "trigger" );

	level notify ( "stopJapChatter" );
	passenger notify ( "stop" );
	driver notify ( "stop" );

	driver SetGoalNode( getNode( "driverReturn", "targetname" ) );
	passenger SetGoalNode( getNode( "passengerReturn", "targetname" ) );

	wait ( 1.8 );
	//passenger waittill ( "goal" );

	driver delete();
	passenger delete();
	printLn( "Deleting Driver + Passenger." );

	truck playSound( "truck_door_open", "door_open" );
	truck waittill ( "door_open" );
	truck playSound( "truck_door_close", "door_close" );
	truck waittill ( "door_close" );
	printLn( "Truck Guys Leaving." );

	//vehicleGuys = [];
	//vehicleGuys[ vehicleGuys.size ] = driver;
	//vehicleGuys[ vehicleGuys.size ] = passenger;

	//truck.vehicletype = "model94"; // Need This To Avoid Re-Enter Bug?

	//maps\_vehicle_aianim::guy_array_enter( vehicleGuys, truck );

	truckGateTrig = getEnt( "bridgeTruckGo", "targetname" );
	assert( isDefined( truckGateTrig ) );
	truckGateTrig notify ( "trigger" );
	printLn( "Truck Gate Trigger Activated." );

	flag_wait_all( "off_boat_1", "off_boat_2" );
	println( "Boat 1 and Boat 2 arrived at the shore." );

	// Player Getting Off Hacked Anim
	spot1 = getStruct( "player_boatunload_pos1", "targetname" );
	assert( isDefined( spot1 ) );
	spot2 = getStruct( "player_boatunload_pos2", "targetname" );
	assert( isDefined( spot2 ) );
	spot3 = getStruct( "player_boatunload_pos3", "targetname" );
	assert( isDefined( spot3 ) );

	lerptime = 1;
	playerSpot unLink(); // From Boat
	playerSpot moveto( spot1.origin, lerptime, lerptime * 0.25 );
	playerSpot rotateTo( spot1.angles, lerptime, lerptime * 0.25 );
	playerSpot waittill ( "movedone" );
	playerSpot moveto( spot2.origin, lerptime, lerptime * 0.25 );
	playerSpot rotateTo( spot2.angles, lerptime, lerptime * 0.25 );
	playerSpot waittill ( "movedone" );
	playerSpot moveto( spot3.origin, lerptime, lerptime * 0.25 );
	playerSpot rotateTo( spot3.angles, lerptime, lerptime * 0.25 );
	playerSpot waittill ( "movedone" );

	println( "Unloading player." );
	flag_set( "player_unloading" );

	players = get_players();
	for( x = 0 ; x < players.size ; x++ )
	{
		player = players[ x ];
		player unLink(); // From Script Origin
		player EnableWeapons();
		player SetClientDvar( "hud_showStance", "1" );
		player SetClientDvar( "compass", "1" );
		player SetClientDvar( "ammoCounterHide", "0" );
		player setclientdvar("miniscoreboardhide","0");
		player AllowCrouch( true );
		player AllowProne( true );
	}

	if( is_coop() )
	{
		players = get_players();
		for( x = 1 ; x < players.size ; x++ )
		{
			beachPlayerSpot = getStruct( "beach_playerspawn_" + x, "targetname" );
			assert( isDefined( beachPlayerSpot ) );

			players[ x ] thread coop_warp_player( beachPlayerSpot );
		}
	}

	wait ( 1 );

	players = get_players();
	for( x = 0 ; x < players.size ; x++ )
	{
		num = players[ x ] GetEntityNumber();
		level._player_breadcrumbs[ num ][ 0 ].pos = players[ x ].origin;
		level._player_breadcrumbs[ num ][ 0 ].ang = players[ x ].angles;
	}

	show_all_player_models();

	level.redShirt1 gun_recall();
	level.redShirt2 gun_recall();

	level thread maps\_utility::autosave_by_name( "fresh_off_the_boat" );

	thread introBeach();
}

introRideJapChatter( guy, guy2 )
{
	level endon ( "stopJapChatter" );

	while( 1 )
	{
		guy speak( "JA_0_reaction_casualty_generic" );

		guy2 speak( "JA_0_threat_direction_nthwest" );

		guy speak( "JA_0_cough_medium" );

		wait ( 1 );

		guy speak( "JA_3_threat_direction_nthwest" );

		guy2 speak( "JA_3_status_check" );

		wait ( 0.5 );

		guy2 speak( "JA_3_direction_relative_northwest" );

		guy speak( "JA_2_status_response" );

		wait ( 1 );
	}
}

boatLogic()
{
	self StartPath();

	self waittill ( "reached_end_node" );

	println( "Boat made it to end node. Index: " + self.num );

	flag_set( "off_boat_" + self.num );

	if( ( self.num == 1 ) )
	{
		flag_wait( "player_unloading" );
	}

	self notify ( "exit_boat" );

	for( x = 0 ; x < self.guys.size ; x++ )
	{
		self.guys[ x ] Unlink();
	}

	anim_single( self.guys, "exit", undefined, self );
}

truckHeadLights( name )
{
	truck = getEnt( name, "targetname" );

	if( isDefined( truck ) )
	{
		playFxOnTag(level._effect["truck_headlights"], truck, "tag_headlight_right");
		playFxOnTag(level._effect["truck_headlights"], truck, "tag_headlight_left");
	}
}

introBeach()
{
	blocker = getEnt( "beach_playerblock", "targetname" );

	allies = GetAIArray( "allies" );
	assert( allies.size > 0 );

	for( x = 0 ; x < allies.size ; x++ )
	{
		allies[ x ].oldMovePlayBack = self.moveplaybackrate;
		allies[ x ].moveplaybackrate = ( allies[ x ].moveplaybackrate / 2 );
		allies[ x ] cqb_walk( "on" );
	}

	wait ( 2 );

	level.Roebuck setGoalNode( getNode( "beach_roebuck_crouch", "targetname" ) );
	level.Sullivan setGoalNode( getNode( "beach_sullivan_crouch", "targetname" ) );
	level.Polonsky setGoalNode( getNode( "beach_polonsky_crouch", "targetname" ) );
	level.redShirt1 setGoalNode( getNode( "beach_redShirt1_crouch", "targetname" ) );
	level.redShirt2 setGoalNode( getNode( "beach_redShirt2_crouch", "targetname" ) );

	level.Roebuck speak( "eyes_open" );

	level.redShirt1 speak( "ever_seen_banzai" );

	level.redShirt1 speak( "a_what" );

	level.redShirt1 speak( "a_banzai" );

	wait ( 0.83 );

	level.redShirt1 speak( "crazy_tactic" );

	//iPrintLnBold( "^1Roebuck: ^7Shhh." );
	level.Roebuck speak( "shhh" );

	wait ( 1 );

	//iPrintLnBold( "^1Sullivan: ^7You hear something?" );
	level.Sullivan speak( "hear_something" );

	wait ( 1.2 );

	level.Roebuck speak( "stick_with_me" );

	blocker ConnectPaths();

	executionSpot = getStruct( "execution_goalpos", "targetname" );
	level.Sullivan setGoalPos( executionSpot.origin );
	level.Polonsky setGoalPos( executionSpot.origin );
	level.redShirt1 setGoalPos( executionSpot.origin );

	executionSceneReady();

	wait ( 1.8 );

	thread executionScene();

	wait ( 1 );

	//iPrintLnBold( "^1Sullivan: ^7Come Here" );
	level.Sullivan speak( "come_here" );

	blocker notSolid();
	blocker delete();
}

executionSceneReady()
{
	Sullivan = false;
	Polonsky = false;
	RedShirt1 = false;

	trigger = getEnt( "execution_scene_ready", "targetname" );
	assert( isDefined( trigger ) );

	while( 1 )
	{
		if( level.Sullivan isTouching( trigger ) )
		{
			Sullivan = true;
		}

		if( level.Polonsky isTouching( trigger ) )
		{
			Polonsky = true;
		}

		if( level.redShirt1 isTouching( trigger ) )
		{
			RedShirt1 = true;
		}

		if( Sullivan && Polonsky && RedShirt1 )
		{
			break;
		}

		wait ( 0.05 );
	}
}

executionScene()
{
	animSpot = getStruct( "execution_spot", "targetname" );
	patrollerSpawner = getEnt( "execution_patroller", "targetname" );

	patroller = patrollerSpawner StalingradSpawn();
	if ( spawn_failed( patroller ) )
	{
		assertMsg( "Patrol Victim Didn't Spawn." );
		return;
	}

	patroller.ignoreme = true;
	patroller.anim_disableLongDeath = true;
	patroller.pathenemyfightdist = 0;
	patroller.pathenemylookahead = 0;
	patroller.nodeathragdoll = true;
	patroller.grenadeammo = 0;
	patroller.dropweapon = 0;
	patroller.animname = "execution_patroller";
	patroller.targetname = "execution_patroller";
	patroller animscripts\shared::DropAIWeapon();

	guys = [];
	guys[ guys.size ] = level.Polonsky;
	guys[ guys.size ] = level.Sullivan;
	guys[ guys.size ] = level.redShirt1;

	patroller.executioner = guys[ 1 ];

	patroller.deathanim = level.scr_anim["execution_patroller"]["execute"];
	newOrigin = GetStartOrigin( animSpot.origin, animSpot.angles, patroller.deathanim );
	newAngles = GetStartAngles( animSpot.origin, animSpot.angles, patroller.deathanim );
	patroller Teleport( newOrigin, newAngles );

	animSpot thread anim_loop_solo( patroller, "execution_idle", undefined, "stop_idle_loop" );
	animSpot thread anim_loop( guys, "execution_idle", undefined, "stop_idle_loop" );

	wait ( 0.05 );

	trigger_wait ( "beach_execution_go", "targetname" );

	animSpot notify ( "stop_idle_loop" );
	array_thread( guys, ::anim_stopanimscripted );
	patroller anim_stopanimscripted();

	allGuys = guys;
	guy2 = guys[0];
	guys = array_remove( guys, guy2 );

	level thread headShotFX( patroller );
	patroller DoDamage( patroller.health + 5, (0,0,0) );

	patroller thread executionPlayerInteracted( allGuys );

	animSpot thread anim_single_solo( guy2, "execute" );
	animSpot thread anim_single( guys, "execute" );

	guys[0] waittillmatch (  "single anim", "end" );

	flag_set( "execution_done" );
}

executionPlayerInteracted( redshirts )
{
	level endon ( "execution_done" );

	while( 1 )
	{
		self waittill ( "damage", amount, attacker );

		if( IsPlayer( attacker ) )
		{
			break;
		}
	}

	level notify ( "execution_interrupted" );

	self anim_stopanimscripted();
	self startRagDoll();
}

bulletShotFX( executioner )
{
	level endon ( "execution_interrupted" );

	PlayFxOnTag( level._effect["rifleflash"], executioner, "tag_flash" );

	wait ( 0.2 );

	PlayFxOnTag( level._effect["rifle_shelleject"], executioner, "tag_brass" );
}

headShotFX( victim )
{
	level endon ( "execution_interrupted" );

	executioner = victim.executioner;

	victim waittillmatch ( "deathanim", "head_shot" );

	if( is_mature() )
	{
		forward = AnglesToForward( ( executioner GetTagAngles( "tag_flash" ) ) );
		PlayFX( level._effect["headshot"], victim GetTagOrigin( "J_Brow_LE" ), forward );
		victim PlaySound( "bullet_large_flesh" );

		wait ( 0.3 );

		PlayFxOnTag( level._effect["bloodspurt"], victim, "J_Brow_LE" );

		wait ( 1.6 );

		PlayFxOnTag( level._effect["bloodspurt"], victim, "J_Brow_LE" );
	}
}